package com.ptl.bp.config;


import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.format.FormatterRegistry;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Date;
import java.util.TimeZone;


@Configuration
public class SerializerConfig {

    /**
     * 配置URL参数中的日期时间转换
     */
    @Bean
    public WebMvcConfigurer dateTimeFormatterConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addFormatters(FormatterRegistry registry) {
                DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
                registrar.setDateFormatter(Const.DATE_FORMATTER);
                registrar.setTimeFormatter(Const.TIME_FORMATTER);
                registrar.setDateTimeFormatter(Const.DATE_TIME_FORMATTER);
                registrar.registerFormatters(registry);

                // 注册传统 Date 类型的转换器
                registry.addConverter(String.class, Date.class, source -> {
                    try {
                        return new SimpleDateFormat(Const.DATE_TIME_FORMAT).parse(source);
                    } catch (Exception e) {
                        throw new IllegalArgumentException("日期格式必须为: " + Const.DATE_TIME_FORMAT);
                    }
                });
            }
        };
    }

    /**
     * 配置body参数中的日期时间转换,处理使用json序列化, eg: 接收body中参数 或者返回值
     */
    @Primary
    @Bean
    public ObjectMapper getObjectMapper() {
        ObjectMapper objectMapper = new ObjectMapper();
        // 忽略未知字段（不报错）
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

        JavaTimeModule module = new JavaTimeModule();

        // === 1. 配置 Date（java.util.Date）===
        // 序列化：支持 ISO 8601 和 yyyy-MM-dd HH:mm:ss
        module.addSerializer(Date.class, new DateSerializer(false, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")));
        // 反序列化：支持 ISO 8601、UTC 和 yyyy-MM-dd HH:mm:ss
        module.addDeserializer(Date.class, new CustomDateDeserializer());

        // === 2. 配置 LocalDate（仅日期，如 "2023-10-01"）===
        module.addSerializer(LocalDate.class, new LocalDateSerializer(DateTimeFormatter.ISO_LOCAL_DATE));
        module.addDeserializer(LocalDate.class, new LocalDateDeserializer(DateTimeFormatter.ISO_LOCAL_DATE));

        // === 3. 配置 LocalTime（仅时间，如 "14:30:15"）===
        module.addSerializer(LocalTime.class, new LocalTimeSerializer(DateTimeFormatter.ISO_LOCAL_TIME));
        module.addDeserializer(LocalTime.class, new LocalTimeDeserializer(DateTimeFormatter.ISO_LOCAL_TIME));

        // === 4. 配置 LocalDateTime（日期 + 时间，如 "2023-10-01T14:30:15" 或 "2023-10-01 14:30:15"）===
        // 序列化：默认 ISO 格式（带 "T"），但可以自定义
        module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
        // 反序列化：支持 ISO 格式（带 "T"）、UTC 时间戳和 yyyy-MM-dd HH:mm:ss
        module.addDeserializer(LocalDateTime.class, new CustomLocalDateTimeDeserializer());

        objectMapper.registerModule(module);

        // 设置时区为 UTC（可选，如果需要统一使用 UTC 时间）
        objectMapper.setTimeZone(TimeZone.getTimeZone("UTC"));

        return objectMapper;
    }

    public static class CustomDateDeserializer extends JsonDeserializer<Date> {
        private static final SimpleDateFormat[] DATE_FORMATS = {
                new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"),
                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"), // ISO 8601
                new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")      // ISO 8601（无毫秒）
        };

        static {
            for (SimpleDateFormat format : DATE_FORMATS) {
                format.setTimeZone(TimeZone.getTimeZone("UTC")); // 设置 UTC 时区
            }
        }

        @Override
        public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            String dateStr = p.getText();
            for (SimpleDateFormat format : DATE_FORMATS) {
                try {
                    return format.parse(dateStr);
                } catch (ParseException ignored) {
                    // 尝试下一种格式
                }
            }
            throw new IllegalArgumentException("Unsupported date format: " + dateStr);
        }
    }

    public static class CustomLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
        private static final DateTimeFormatter[] FORMATTERS = {
                DateTimeFormatter.ISO_LOCAL_DATE_TIME,          // "2023-10-01T14:30:15"
                DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"), // "2023-10-01 14:30:15"
                DateTimeFormatter.ISO_DATE_TIME.withZone(ZoneId.of("UTC")) // ISO 8601 + UTC
        };

        @Override
        public LocalDateTime deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
            String dateTimeStr = p.getText();
            for (DateTimeFormatter formatter : FORMATTERS) {
                try {
                    return LocalDateTime.parse(dateTimeStr, formatter);
                } catch (DateTimeParseException ignored) {
                    // 尝试下一种格式
                }
            }
            throw new IllegalArgumentException("Unsupported LocalDateTime format: " + dateTimeStr);
        }
    }
}